package com.cap6402.project.two;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.android.ex.carousel.*;
import com.facebook.android.R;

import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class ChooseLevelActivity extends Activity{
    private static final int CARD_SLOTS = 56;
    private static final int TOTAL_CARDS = 4;
    private static final int TEXTURE_HEIGHT = 100;
    private static final int TEXTURE_WIDTH = 100;
    private static final int SLOTS_VISIBLE = 7;

    protected static final boolean DBG = false;
    
    private static final int DETAIL_TEXTURE_WIDTH = 200;
    private static final int DETAIL_TEXTURE_HEIGHT = 80;
    private static final int VISIBLE_DETAIL_COUNT = 3;
    private Paint mPaint = new Paint();
    private CarouselViewHelper mHelper;
    private Bitmap mGlossyOverlay;
    private Bitmap mBorder;
	public final static String query = "SELECT name,uid,pic FROM user " +
			"WHERE uid IN (SELECT uid2 FROM friend WHERE uid1 = me()) " +
			"AND is_app_user = 1";
	private boolean isDone = false;
	private boolean everythingLoaded = false;
	
	Handler mHandler = new Handler();
	ProgressDialog progressDialog;
	ProgressThread progressThread;
	JSONArray jArray;
	String result = null;
	InputStream is = null;
	StringBuilder sb=null;
	FriendCarouselView carouselView;
	HashMap<Integer,Friend> people = new HashMap<Integer,Friend>();
	HashMap<String,Friend> friends = new HashMap<String,Friend>();
	HashMap<String,Integer> scoreValues;
	//how many cards loaded
	int actualNumOfCards = 1;
	//how many friends will be displayed (including me)
	int totalCards;
	
	JSONArray scores;
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.level);
	    final Resources res = getResources();
        carouselView = (FriendCarouselView) findViewById(R.id.carousel);
        carouselView.getHolder().setFormat(PixelFormat.RGBA_8888);
        mHelper = new LocalCarouselViewHelper(ChooseLevelActivity.this);
        mHelper.setCarouselView(carouselView);
        carouselView.setSlotCount(CARD_SLOTS);
        carouselView.setVisibleSlots(SLOTS_VISIBLE);
        carouselView.setStartAngle((float) -(2.0f*Math.PI * 5 / CARD_SLOTS));
        mBorder = BitmapFactory.decodeResource(res, R.drawable.border);
        carouselView.setDefaultBitmap(mBorder);
        carouselView.setLoadingBitmap(mBorder);
        Bitmap bg = BitmapFactory.decodeResource(res, R.drawable.bg);
        carouselView.setBackgroundBitmap(bg);
        carouselView.setBackgroundColor(0.25f, 0.25f, 0.5f, 0.5f);
        carouselView.setRezInCardCount(3.0f);
        carouselView.setFadeInDuration(250);
        carouselView.setVisibleDetails(VISIBLE_DETAIL_COUNT);
        carouselView.setDragModel(CarouselView.DRAG_MODEL_PLANE);
        mGlossyOverlay = BitmapFactory.decodeResource(res, R.drawable.glossy_overlay);
        showDialog(Utility.LOAD_LEVELS_DIALOG);
	}
	@Override
    protected Dialog onCreateDialog(int id) {
        switch(id) {
        case Utility.LOAD_LEVELS_DIALOG:
            progressDialog = new ProgressDialog(ChooseLevelActivity.this);
            progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
            progressDialog.setMessage("Loading Friends/Scores...");
            progressDialog.setCancelable(false);
            return progressDialog;
        default:
            return null;
        }
    }
    @Override
    protected void onPrepareDialog(int id, Dialog dialog) {
        switch(id) {
        case Utility.LOAD_LEVELS_DIALOG:
            progressDialog.setProgress(0);
            progressThread = new ProgressThread(handler);
            progressThread.start();
        break;
        }
    }
    
    final Handler handler = new Handler() {
    	public void handleMessage(Message msg) {
    		int state = msg.arg1;
    		if(everythingLoaded) {
    			dismissDialog(Utility.LOAD_LEVELS_DIALOG);
    			progressThread.setState(ProgressThread.STATE_DONE);
    		}
    	}
    };
	
	private void getFriendsWhoUseApp() {
		Bundle params = new Bundle();
		params.putString("method", "fql.query");
		params.putString("query", query);
		Utility.mAsyncRunner.request(null,params, new FQLRequestListener());
	}
	
	/*
	 * Callback for getting FQL Query Result
	 * 
	 */
	private class FQLRequestListener extends BaseRequestListener {

		@Override
		public void onComplete(String response, Object state) {
			// TODO Auto-generated method stub
			JSONArray json = null;
			try {
				json = new JSONArray(response);
				if(json.length() == 0) {
					totalCards = json.length()+1;
					mHandler.post(new Runnable() {

						@Override
						public void run() {
							new GetScoresAsyncTask().execute();
						}
						
					});
					return;
				}
				if(!json.getJSONObject(0).getString("uid").equals(Utility.userID)) {
					totalCards = json.length()+1;
				}
			} catch (JSONException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			for(int i = 0; i < json.length(); i++) {
				JSONObject object;
				try {
					object = json.getJSONObject(i);
					final String friendId = object.getString("uid");
					final String friendName = object.getString("name");
					final String friendPicURL = object.getString("pic");
					
					mHandler.post(new Runnable() {

						@Override
						public void run() {
							new GetProfilePicAsyncTask().execute(friendId,friendName,friendPicURL);
						}
						
					});

					
				} catch(JSONException e) {
					e.printStackTrace();
				}
			}
		}
		
	}
	
	private class MeRequestListener extends BaseRequestListener {
		@Override
		public void onComplete(String response, Object state) {
            JSONObject jsonObject;
            try {
                jsonObject = new JSONObject(response);
                Utility.userID = jsonObject.getString("id");
                Utility.name = jsonObject.getString("name");
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    		Bundle params = new Bundle();
    		params.putString("method", "fql.query");
    		params.putString("query", "select uid,pic,name from user where uid=me()");
    		Utility.mAsyncRunner.request(null,params, new FQLRequestListener());
            
		}
	}
	
	private class GetProfilePicAsyncTask extends AsyncTask<String, Void, Friend> {
		@Override
		protected Friend doInBackground(String... arg0) {
			URL url = null;
			Bitmap mBitmap = null;
			try {
				url = new URL(arg0[2]);
				URLConnection connection = url.openConnection();
			      BitmapFactory.Options bitopt=new BitmapFactory.Options();
			        bitopt.inMutable=true;
				mBitmap = BitmapFactory.decodeStream(connection.getInputStream(),null,bitopt);
			} catch (MalformedURLException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			Friend friend = new Friend(arg0[0],arg0[1],mBitmap);
			return friend;
		}
		
		@Override
		protected void onPostExecute(Friend friend) {
			if(friend.id.equals(Utility.userID)) {
				isDone = true;
				people.put(0, friend);
				friends.put(Utility.userID,friend);
			}
			else {
				people.put(actualNumOfCards++, friend);
				friends.put(friend.id, friend);
			}
			Utility.levelScores.put(friend.id, new LinkedHashMap<String,Integer>());
	        //stupid callbacks
	        if(isDone) {
	        	isDone = false;
	    		getFriendsWhoUseApp();
	        }
	        
	        if(people.size() == totalCards) {
	        	mHandler.post(new Runnable() {

					@Override
					public void run() {
						new GetScoresAsyncTask().execute();
					}
	        		
	        	});
	        }
		}
	}
	
	private class GetScoresAsyncTask extends AsyncTask<Void, Void, String> {

		@Override
		protected String doInBackground(Void... arg0) {
			try{
				HttpClient httpclient = new DefaultHttpClient();
				HttpPost httppost = new HttpPost("http://cise.ufl.edu/~acordar/socialnetwork/socialnetworkdbservice.php");
				//httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
				HttpResponse response = httpclient.execute(httppost);
				HttpEntity entity = response.getEntity();
				is = entity.getContent();
			}catch(Exception e){
				Log.e("log_tag", "Error in http connection"+e.toString());
			}
			try{
				BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
				sb = new StringBuilder();
				sb.append(reader.readLine() + "\n");

				String line="0";
				while ((line = reader.readLine()) != null) {
					sb.append(line + "\n");
				}
				is.close();
				result=sb.toString();
			}catch(Exception e){
				Log.e("log_tag", "Error converting result "+e.toString());
			}
			
			return result;
		}
		
		@Override
		protected void onPostExecute(String result) {
			Log.i("RESULT", result);
			JSONArray json = null;
			try {
				json = new JSONArray(result);
				scores = json;
				for(int i = 0; i < json.length(); i++) {
					JSONObject object;
					object = json.getJSONObject(i);
					final String userId = object.getString("user_id");
					final String levelId = object.getString("level_id");
					final String score = object.getString("score");	
					final String name = object.getString("name");
					if(Utility.levelScores.get(levelId) != null)
						Utility.levelScores.get(levelId).put(userId,Integer.parseInt(score));

				}
			} catch(JSONException e) {
				e.printStackTrace();
			}
			everythingLoaded = true;
			mHandler.post(new Runnable() {

				@Override
				public void run() {
		            carouselView.createCards(totalCards);
				}
				
			});
			
		}
	}
	
    class LocalCarouselViewHelper extends CarouselViewHelper {
        private static final int PIXEL_BORDER = 3;
        private DetailTextureParameters mDetailTextureParameters
                = new DetailTextureParameters(5.0f, 5.0f, 3.0f, 10.0f);

        LocalCarouselViewHelper(Context context) {
            super(context);
        }

        @Override
        public void onCardSelected(final int id) {
			Intent intent = new Intent(ChooseLevelActivity.this, SocialNetworkActivity.class);
			intent.putExtra("user", people.get(id).id);
			startActivity(intent);
            //postMessage("Selection", "Card " + id + " was selected");
        }

        @Override
        public void onDetailSelected(final int id, int x, int y) {
            //postMessage("Selection", "Detail for card " + id + " was selected");
        }

        @Override
        public void onCardLongPress(final int n, int touchPosition[], Rect detailCoordinates) {

        	runOnUiThread(new Runnable(){

				@Override
				public void run() {
		        	final Dialog dialog = new Dialog(ChooseLevelActivity.this);
		        	dialog.setContentView(R.layout.hiscorelist);
		        	dialog.setTitle("High Scores");
		        	ListView lv = (ListView) dialog.findViewById(R.id.listView1);
		        	HashMap<String,Integer> vals = Utility.levelScores.get(people.get(n).id);
		        	if(vals.size() == 0) {
		        		Toast.makeText(ChooseLevelActivity.this, "No High Scores", Toast.LENGTH_SHORT).show();
		        		return;
		        	}
		        	scoreValues = vals;
		        	ArrayList<Integer> sco = new ArrayList<Integer>(vals.values());
		        	//Collections.reverse(sco);
		        	lv.setAdapter(new ScoreListAdapter(ChooseLevelActivity.this,sco));
		        	dialog.show();
				}
        		
        	});
            //postMessage("Selection", "Long press on card " + n);
        }

        @Override
        public DetailTextureParameters getDetailTextureParameters(int id) {
            return mDetailTextureParameters;
        }

        @Override
        public Bitmap getTexture(int n) {
        	Friend friend = people.get(n);
        	Bitmap bitmap = null;
        	//Bitmap bitmap = Bitmap.createBitmap(TEXTURE_WIDTH, TEXTURE_HEIGHT,
            //        Bitmap.Config.ARGB_8888);
        	if(friend != null) {
        		 bitmap = Bitmap.createScaledBitmap(friend.profilePic, 100, 100, true);
        	} else {
               	 bitmap = Bitmap.createBitmap(TEXTURE_WIDTH, TEXTURE_HEIGHT,
                        Bitmap.Config.ARGB_8888);
        	}
            Canvas canvas = new Canvas(bitmap);
            canvas.drawARGB(0, 0, 0, 0);
            mPaint.setColor(0x40808080);
            canvas.drawRect(0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT, mPaint);
            mPaint.setTextSize(100.0f);
            mPaint.setAntiAlias(true);
            mPaint.setColor(0xffffffff);
            //canvas.drawText("" + n, 2, TEXTURE_HEIGHT-10, mPaint);
            canvas.drawBitmap(mGlossyOverlay, null,
                    new Rect(0, 0,
                            TEXTURE_WIDTH - 0, TEXTURE_HEIGHT - 0), mPaint);
            return bitmap;
        }

        @Override
        public Bitmap getDetailTexture(int n) {
            Bitmap bitmap = Bitmap.createBitmap(DETAIL_TEXTURE_WIDTH, DETAIL_TEXTURE_HEIGHT,
                    Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);
            canvas.drawARGB(32, 10, 10, 10);
            mPaint.setTextSize(15.0f);
            mPaint.setAntiAlias(true);
            canvas.drawText(people.get(n).name, 0,DETAIL_TEXTURE_HEIGHT/2, mPaint);
            String score = "0";
            if(Utility.levelScores.get(people.get(n).id).get(Utility.userID) != null)
            	score = Utility.levelScores.get(people.get(n).id).get(Utility.userID).toString();
            if(score == null)
            	score = "0";
            canvas.drawText("My High Score: " + score, 0,DETAIL_TEXTURE_HEIGHT/2+15, mPaint);
            //canvas.drawText("Detail text for card " + n, 0, DETAIL_TEXTURE_HEIGHT/2, mPaint);
            return bitmap;
        }
    }
    
    private class Friend {
    	String id;
    	String name;
    	Bitmap profilePic;
    	public Friend(String id, String name, Bitmap profilePic) {
    		this.id = id;
    		this.name = name;
    		this.profilePic = profilePic;
    	}
    }
    private class ProgressThread extends Thread {
    	Handler mHandler;
    	final static int STATE_DONE = 0;
    	final static int STATE_RUNNING = 1;
    	int mState;
    	int total = 0;
    	
    	ProgressThread(Handler h) {
    		this.mHandler = h;
    	}
    	
    	public void run() {
    		mState = STATE_RUNNING;
    		ChooseLevelActivity.this.mHandler.post(new Runnable() {

				@Override
				public void run() {
					// TODO Auto-generated method stub
			        Utility.mAsyncRunner.request("me", new MeRequestListener());
				}
    		});
    		
    		while(mState == STATE_RUNNING) {
    			Message msg = mHandler.obtainMessage();
    			msg.arg1 = mState;
    			mHandler.sendMessage(msg);
    			this.total = progressDialog.getProgress();
    			if(everythingLoaded)
    				mState = STATE_DONE;
    		}
    	}
    	
    	public void setState(int state) {
    		mState = state;
    	}
    }
    
    private class ScoreListAdapter extends BaseAdapter {
    	private LayoutInflater mInflater;
    	ArrayList<Integer> list;
        public ScoreListAdapter(Context context, ArrayList<Integer> list) {
            mInflater = LayoutInflater.from(context);
            this.list = list;
        }
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null) {
                convertView = mInflater.inflate(R.layout.hiscorelist, parent, false);
            }
            TextView score = (TextView) convertView.findViewById(R.id.score);
            TextView name = (TextView) convertView.findViewById(R.id.name);
     
            Integer val = list.get(position);
            score.setText(val.toString() + " Points");
            if(friends.get(scoreValues.keySet().toArray()[position]) == null)
				try {
					name.setText(scores.getJSONObject(position).getString("name"));
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			else
            	name.setText(friends.get(scoreValues.keySet().toArray()[position]).name);
            return convertView;
        }
        public int getCount() {
            return list.size();
        }
        
        public Object getItem(int arg0) {
            return list.get(arg0);
        }
        public long getItemId(int arg0) {
            return arg0;
        }
    }
	

}
